package com.dlyk.config;



import com.dlyk.config.filter.TokenVerifyFilter;
import com.dlyk.config.handler.MyAccessDeniedHandler;
import com.dlyk.config.handler.MyAuthenticationFailureHandler;
import com.dlyk.config.handler.MyAuthenticationSuccessHandler;
import com.dlyk.config.handler.MyLogoutSuccessHandler;
import com.dlyk.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@EnableMethodSecurity//开启方法级别的权限检查
@Configuration //这是配置类，相当于原来spring的xml配置
public class SecurityConfig {

    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;

    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;

    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private TokenVerifyFilter tokenVerifyFilter;

    @Resource
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Bean //There is no PasswordEncoder mapped for the id "null"
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception {
        //禁用跨站请求伪造
        return httpSecurity
                .formLogin((formLogin)->{
                    formLogin.loginProcessingUrl(Constants.LOGIN_URL)//登录处理地址，不需要写controller
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);

                })

                .authorizeHttpRequests((authorize)->{
                    authorize.requestMatchers("/api/login").permitAll()
                            .anyRequest().authenticated();//其他任何请求都需要登录后才能访问
                })

                .csrf(AbstractHttpConfigurer::disable)//禁用跨站请求伪造

                //支持跨域请求
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })

                .sessionManagement((session)->{
                    //session创建策略
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);//无session状态，也就是禁用session
                })

                //添加自定义的Filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)

                //退出登录
                .logout((logout)->{
                    logout.logoutUrl(Constants.LOGOUT_URL)//退出提交到该地址，该地址不需要我们写controller的，是框架处理
                            .logoutSuccessHandler(myLogoutSuccessHandler);
                })

                //这个是没有权限访问时触发
                .exceptionHandling((exceptionHandling)->{
                    exceptionHandling.accessDeniedHandler(myAccessDeniedHandler);
                })

                .build();
    }


    @Primary
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));//允许任何来源，http://localhost:8080
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));//允许任何请求方法，post、get、put、delete
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));//允许任何请求头

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }


}
